package com.course.web.component.custom;

import com.course.constant.MarkTitle;
import com.course.domain.dao.ExamDao;
import com.course.domain.model.Exam;
import com.course.web.biz.WebClassBiz;
import com.course.web.biz.WebStudentBiz;
import com.course.web.component.base.BaseList;
import com.course.web.model.ClassItemVM;
import com.course.web.model.ClassMarkVM;
import com.course.web.model.StudentVM;
import com.course.web.view.TeacherHomeView;
import com.vaadin.data.BeanValidationBinder;
import com.vaadin.data.Binder;
import com.vaadin.data.converter.StringToDateConverter;
import com.vaadin.server.ExternalResource;
import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.ViewScope;
import com.vaadin.ui.*;
import com.vaadin.ui.renderers.DateRenderer;
import com.vaadin.ui.renderers.Renderer;
import com.vaadin.ui.themes.ValoTheme;
import org.springframework.beans.factory.annotation.Autowired;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.List;

/**
 * Created by Justin on 2017/6/15.
 */
@SpringComponent
@ViewScope
public class ClassItemForm extends CustomComponent {

    private final WebStudentBiz studentBiz;
    private final WebClassBiz classBiz;
    private final MarkList markList;
    private final Link roomLink;
    private final Link classLink;
    private final Link studentLink;
    private final Link reportLink;
    private final Binder<ClassMarkVM> binder;

    private final ExamDao examDao;

    private ClassMarkVM mark;

    @Autowired
    public ClassItemForm(WebStudentBiz studentBiz, WebClassBiz classBiz, ExamDao examDao) {
        this.studentBiz = studentBiz;
        this.classBiz = classBiz;
        this.examDao = examDao;
        this.markList = new MarkList();
        this.roomLink = new Link();
        this.classLink = new Link();
        this.studentLink = new Link();
        this.reportLink = new Link();
        this.binder = new BeanValidationBinder<>(ClassMarkVM.class);
        init();
    }

    private void init() {
        Panel panel = new Panel();
        VerticalLayout root = new VerticalLayout();
        HorizontalLayout info = new HorizontalLayout();
        HorizontalLayout main = new HorizontalLayout();
        HorizontalLayout bars = new HorizontalLayout();
        VerticalLayout form = new VerticalLayout();
        TextField teacher = new TextField("Teacher:");
        TextField student = new TextField("Student:");
        TextField title = new TextField("ClassName:");
        TextField begin = new TextField("BeginTime:");
        teacher.setEnabled(false);
        student.setEnabled(false);
        title.setEnabled(false);
        begin.setEnabled(false);
        TextArea suggest = new TextArea(MarkTitle.SUGGEST);
        TextArea comment = new TextArea(MarkTitle.COMMENT);
        TextArea message = new TextArea(MarkTitle.MESSAGE);
        RadioButtonGroup<Integer> mark1 = newMarkRatio(MarkTitle.MARK1);
        RadioButtonGroup<Integer> mark2 = newMarkRatio(MarkTitle.MARK2);
        RadioButtonGroup<Integer> mark3 = newMarkRatio(MarkTitle.MARK3);
//        RadioButtonGroup<Integer> mark4 = newMarkRatio(MarkTitle.MARK4);
//        RadioButtonGroup<Integer> mark5 = newMarkRatio(MarkTitle.MARK5);
        Button mine = new Button("Mine");
        Button save = new Button("Save");
        Button back = new Button("Back");
        info.addComponent(teacher);
        info.addComponent(student);
        info.addComponent(title);
        info.addComponent(begin);
        root.addComponent(info);
        root.addComponent(main);
        main.addComponent(panel);
        main.addComponentsAndExpand(markList);
        form.addComponent(mark1);
        form.addComponent(mark2);
        form.addComponent(mark3);
//        form.addComponent(mark4);
//        form.addComponent(mark5);
        form.addComponent(suggest);
        form.addComponent(comment);
        form.addComponent(message);
        root.addComponent(bars);
        bars.setDefaultComponentAlignment(Alignment.MIDDLE_CENTER);
        bars.addComponent(mine);
        bars.addComponent(save);
        bars.addComponent(back);
        bars.addComponent(roomLink);
        bars.addComponent(classLink);
        bars.addComponent(studentLink);
        bars.addComponent(reportLink);
        panel.setContent(form);
        setCompositionRoot(root);
        setSizeFull();

        panel.setSizeUndefined();
        panel.setHeight("400px");
        form.setWidthUndefined();
        title.setEnabled(false);
        begin.setEnabled(false);
        teacher.setEnabled(false);
        student.setEnabled(false);
        mark1.setCaptionAsHtml(true);
        mark2.setCaptionAsHtml(true);
        mark3.setCaptionAsHtml(true);
//        mark4.setCaptionAsHtml(true);
//        mark5.setCaptionAsHtml(true);
        suggest.setSizeFull();
        comment.setSizeFull();
        message.setSizeFull();

        StringToDateConverter converter = new StringToDateConverter();
        binder.forField(title).bind("task");
        binder.forField(begin).withConverter(converter).bind("date");
        binder.forField(mark1).bind("mark1");
        binder.forField(mark2).bind("mark2");
        binder.forField(mark3).bind("mark3");
//        binder.forField(mark4).bind("mark4");
//        binder.forField(mark5).bind("mark5");
        binder.forField(teacher).bind("teacher");
        binder.forField(student).bind("student");
        binder.forField(suggest).bind("suggest");
        binder.forField(comment).bind("comment");
        binder.forField(message).bind("message");
        this.binder.addStatusChangeListener(event -> save.setEnabled(this.binder.isValid()));

        markList.setSizeFull();
        markList.setHandler(data -> {
            binder.setBean(data);
            boolean enabled = data.getId() == mark.getId();
            save.setEnabled(enabled);
            form.setEnabled(enabled);
        });

        mine.addClickListener(event -> {
            binder.setBean(mark);
            markList.setValue(mark.getId());
            save.setEnabled(binder.isValid());
            form.setEnabled(true);
        });
        save.addClickListener(event -> save());
        back.addClickListener(event -> back());
    }

    private void save() {
        classBiz.updateMark(binder.getBean());
        markList.flush();
        markList.setValue(binder.getBean().getId());
        Notification.show("Thank you! The feedback has been saved.");
    }

    private void back() {
        getUI().getNavigator().navigateTo(TeacherHomeView.NAME);
    }

    public void enter(int itemId) {
        ClassItemVM item = classBiz.loadItem(itemId);
        int studentId = item.getStudentId();
        StudentVM student = studentBiz.load(studentId);
        List<ClassMarkVM> marks = classBiz.findMarkByStudent(studentId);
        marks.stream().filter(data -> data.getId() == itemId).findFirst().ifPresent(binder::setBean);
        mark = binder.getBean();
        if (mark == null) {
            mark = new ClassMarkVM();
            mark.setId(item.getId());
            mark.setStudent(item.getStudent());
            mark.setTeacher(item.getTeacher());
            mark.setTask(item.getTask());
            mark.setDate(item.getDateTime());
            mark.setMark1(1);
            mark.setMark2(1);
            mark.setMark3(1);
            mark.setMark4(1);
            mark.setMark5(1);
        }
        binder.setBean(mark);
        markList.enter(marks);
        markList.setValue(item.getId());
        roomLink.setCaption("Enter class room");
        roomLink.setResource(new ExternalResource("https://www.zoomus.cn/j/" + item.getRoom()));
        classLink.setCaption("Download class PPT");
        classLink.setResource(new ExternalResource(item.getLink()));
        studentLink.setCaption("Download student PPT");
        studentLink.setResource(new ExternalResource(student.getLink()));

        reportLink.setCaption("Download exam report template");
        Exam exam = examDao.findOne(1);
        if (exam != null) {
            reportLink.setResource(new ExternalResource(exam.getReportLink()));
        }
    }

    private RadioButtonGroup<Integer> newMarkRatio(String caption) {
        List<Integer> options = Arrays.asList(1, 2, 3, 4, 5);
        RadioButtonGroup<Integer> group = new RadioButtonGroup<>(caption, options);
        group.setItemCaptionGenerator(String::valueOf);
        group.addStyleName(ValoTheme.OPTIONGROUP_HORIZONTAL);

        return group;
    }

    private class MarkList extends BaseList<ClassMarkVM> {

        MarkList() {
            Renderer renderer = new DateRenderer(new SimpleDateFormat("YYYY-MM-dd HH:mm"));
            addColumn(ClassMarkVM::getTask, "ClassName");
            addColumn(ClassMarkVM::getDate, "BeginTime").setRenderer(renderer);
            addColumn(ClassMarkVM::getTeacher, "Teacher");
        }

        public void enter(List<ClassMarkVM> marks) {
            setItems(marks);
        }
    }
}
